<script setup lang="ts">
import { onMounted, ref, watch, onUpdated } from 'vue'
import { EditorView, minimalSetup } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { oneDark } from '@codemirror/theme-one-dark'
import { ElIcon } from 'element-plus'
import { FullScreen } from '@element-plus/icons-vue'

const codeEditorRef = ref()
const fullScreen = ref(false)

const props = defineProps({
  modelValue: {
    type: String
  }
})
const emit = defineEmits(['update:modelValue'])

let view
// 猜测：modelValue更新会触发渲染导致汉字输入法框显示问题
watch(
  () => props.modelValue,
  (newValue) => {
    if (view && newValue !== view.state.doc.toString()) {
      view.dispatch({
        changes: { from: 0, to: view.state.doc.length, insert: props.modelValue }
      })
    }
  }
)

let updateValue = EditorView.updateListener.of((viewUpdate) => {
  if (viewUpdate.docChanged) {
    emit('update:modelValue', viewUpdate.state.doc.toString())
  }
})

onMounted(() => {
  view = new EditorView({
    doc: props.modelValue,
    extensions: [minimalSetup, oneDark, javascript(), updateValue],
    parent: codeEditorRef.value
  })
})
</script>

<template>
  <teleport to=".editor-body" :disabled="!fullScreen">
    <div class="code-editor-box" :class="fullScreen ? 'full-screen' : ''" @keydown.stop>
      <ElIcon color="#fff" :size="20" class="f-s-button" @click="fullScreen = !fullScreen">
        <FullScreen />
      </ElIcon>
      <div ref="codeEditorRef" class="code-editor"></div>
    </div>
  </teleport>
</template>

<style scoped>
.code-editor-box {
  box-sizing: border-box;
  width: 100%;
  position: relative;
}

.f-s-button {
  cursor: pointer;
}

.code-editor {
  width: 100%;
  overflow: auto;
}

.full-screen {
  height: 100%;
  padding: 25px;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  background-color: rgba(0, 0, 0, 0.8);
}

.full-screen {
  height: 100%;
  padding: 25px;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
}

.full-screen .f-s-button {
  position: absolute;
  left: 2px;
  top: 2px;
  z-index: 1;
}

.full-screen .code-editor {
  height: 100%;
}
</style>
